
#include "debug.h"

static int level_debug = DEBUG_INFO;
static int level_log = DEBUG_ERROR;
static int fg_color=30;
static int bg_color=40;
static char g_name[64] = "_";
static FILE *g_log_fp=NULL;

/***************************************************
  print binary buffer info
***************************************************/
void d_debug_bin_buffer(const unsigned char *data, int len, const char *from)
{
	int i=0;

//if(level_debug<1000) return;		// for disable this function.

	if(level_debug>DEBUG_DEBUG){
		fprintf(stdout, "\n");
		d_debug("%s, len=[%d]\n",from?from:"Unknown", len);
		for( i = 0; i < len; i++ ) {
			if(level_debug!=DEBUG_VERBOSE&&len>30){
				if(i<20||(len-i)<10){
					fprintf(stdout,"[32;41m\\%02X[0m",(unsigned char)*(data+i));
				}else if(i==20){
					fprintf(stdout,"[32;41m\\......\\[0m");
				}
			}else{
				fprintf(stdout,"[32;41m\\%02X[0m",(unsigned char)*(data+i));
			}
		}
		fprintf(stdout, "\n");
	}

	if(g_log_fp&&level_log>DEBUG_DEBUG){
		fprintf(g_log_fp, "\n");
		d_debug("%s, len=[%d]\n",from?from:"Unknown", len);
		for( i = 0; i < len; i++ ) {
#if 0
			if(isprint(*(data+i)) || isspace(*(data+i))){
				fprintf(g_log_fp, "%c",(unsigned char)*(data+i));
			}else
#endif
			{
				if(level_log!=DEBUG_VERBOSE&&len>30){
					if(i<20||(len-i)<10){
						fprintf(g_log_fp, "\\%02X",(unsigned char)*(data+i));
					}else if(i==20){
						fprintf(g_log_fp, "\\......\\");
					}
				}else{
					fprintf(g_log_fp,"\\%02X",(unsigned char)*(data+i));
				}
			}
		}
		fprintf(g_log_fp, "\n");
	}
}

void d_destroy_debug()
{
	time_t t=time(NULL);
	struct tm *ptm = localtime(&t);
	char buf[1024]="";
	if(g_log_fp){
		sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
				ptm->tm_year+1900, ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
		fprintf(g_log_fp,"\n====== End logging [%s] at %s. ======\n", g_name , buf);
		fclose(g_log_fp);
	}
	g_log_fp=NULL;
	memset((void *)g_name,0,sizeof(g_name));
	level_debug=DEBUG_INFO,
	level_log=DEBUG_ERROR;
	fg_color=30;
	bg_color=40;
}

void d_init_debug(char *magic, int level, int log, int fg, int bg)
{
	time_t t=time(NULL);
	struct tm *ptm = localtime(&t);
	char fn[1024]="";

	if(g_log_fp){
		d_destroy_debug();
	}
	memset((void *)g_name,0,sizeof(g_name));
	strncpy(g_name,magic,sizeof(g_name)-1);
	level_debug=level;
	level_log=log;
	fg_color=30+fg;
	bg_color=40+bg;
	memset((void *)fn,0,sizeof(fn));

	if(level_log<=DEBUG_NONE) return;

	strncpy(fn,magic,sizeof(fn)-20);
	sprintf(fn+strlen(fn), "_%04d%02d%02d%02d%02d%02d.log",
			ptm->tm_year+1900, ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
	g_log_fp=fopen(fn,"wb+");
	if(!g_log_fp) return;
	sprintf(fn, "%04d-%02d-%02d %02d:%02d:%02d",
			ptm->tm_year+1900, ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
	fprintf(g_log_fp,"====== Start logging [%s] at %s. ======\n", g_name , fn);

}

int d_print_able(int level)
{
	if(level_debug>=level){
		return 1;
	}

	return 0;
}

int d_get_debug_level()
{
	return level_debug;
}

// set debug level
int d_set_debug_level(int level)
{
	if(level<DEBUG_MIN||level>DEBUG_MAX) return -1;

	level_debug=level;

	return 0;
}

int d_get_log_level()
{
	return level_log;
}

// set log level
int d_set_log_level(int level)
{
	if(level<DEBUG_MIN||level>DEBUG_MAX) return -1;

	level_log=level;

	return 0;
}

// get level string
const char *d_level_string(int level)
{
	const char *ls[]={
#if 0
		"none   ",
		"emerg  ",
		"alert  ",
		"crit   ",
		"error  ",
		"warning",
		"notice ",
		"info   ",
		"debug  ",
		"verbose",
		"unknown"
#else
		"N",
		"E",
		"A",
		"C",
		"E",
		"W",
		"N",
		"I",
		"D",
		"V",
		"U"
#endif
	};
	int ls_num=sizeof(ls)/sizeof(ls[0]);

	if(level<0||level>=ls_num) level=ls_num-1;

	return ls[level];
}

// Return current time in string format
char *strtime()
{
	static char buf[32];
	time_t t = 0;
	struct tm *ptm = NULL;
	struct timeval tv={0,0};

	gettimeofday(&tv,NULL);
	t=tv.tv_sec;
	ptm=localtime(&t);

	sprintf(buf, "%02d:%02d:%02d.%03d",
				ptm->tm_hour, ptm->tm_min, ptm->tm_sec, (int)(tv.tv_usec/1000));
//	sprintf(buf, "%02d:%02d:%02d",
//				ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
	return buf;
}

void __d_debug(int level, const char *filename, const int linenum, char *format, ...)
{
	va_list ap;
	char *ts = strtime();
	const char *ls = d_level_string(level);

	va_start(ap, format);
	if( level <= level_debug ) {
		fprintf(stdout, "[%d;%dm%s|%s|%s[0m ", fg_color, bg_color, ts, ls, filename/*, linenum*/);
		vfprintf(stdout, format, ap);
	}

	if( level <= level_log ) {
		if(g_log_fp){
			fprintf(g_log_fp,"^%s|%s|%s|%s|%d#",g_name, ts, ls, filename, linenum);
			vfprintf(g_log_fp, format, ap);
            fflush(g_log_fp);
		}
	}
	va_end(ap);
}
